home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 476-500 / disk_500 / wiconify / wiconify-source.lzh / Source / wLists.c < prev    next >
C/C++ Source or Header  |  1991-04-19  |  13KB  |  539 lines

  1. /*
  2.  *  WICONIFY    A utility that allows you to iconify any Intuition window
  3.  *              on any screen, and to open WB windows on any screen.
  4.  *
  5.  *  wLists.c    Handles screen, window, and icon lists.
  6.  *
  7.  *  Copyright 1990 by Davide P. Cervone, all rights reserved.
  8.  *  You may use this code, provided this copyright notice is kept intact.
  9.  */
  10.  
  11. #include "wHandler.h"
  12. #include <libraries/dos.h>
  13.  
  14. #define INTUIMESSAGE        ((struct IntuiMessage *)theMessage)
  15.  
  16.  
  17.  
  18. /*
  19.  *  FindScreen()
  20.  *
  21.  *  Start with the first screen
  22.  *  While there are more screens and this one is not the one we want
  23.  *    Go on to the next screen
  24.  *  Return the scren found or NULL
  25.  */
  26.  
  27. WSCREEN *FindScreen(theScreen)
  28. struct Screen *theScreen;
  29. {
  30.    WSCREEN *ChkScreen;
  31.    
  32.    Forbid();
  33.       ChkScreen = FirstScreen;
  34.       while (ChkScreen && ChkScreen->Screen != theScreen)
  35.          ChkScreen = ChkScreen->Next;
  36.    Permit();
  37.    return(ChkScreen);
  38. }
  39.  
  40.  
  41. /*
  42.  *  LinkScreen()
  43.  *
  44.  *  Link the screen structure into the link list of screens
  45.  */
  46.  
  47. void LinkScreen(theScreen)
  48. WSCREEN *theScreen;
  49. {
  50.    Forbid();
  51.    theScreen->Next = FirstScreen; theScreen->Prev = NULL;
  52.    if (FirstScreen) FirstScreen->Prev = theScreen;
  53.    FirstScreen = theScreen;
  54.    Permit();
  55. }
  56.  
  57.  
  58. /*
  59.  *  UnLinkScreen()
  60.  *
  61.  *  Unlink the screen from the linked list
  62.  *  If it is marked for refreshing, remove it from that linked list, too
  63.  */
  64.  
  65.  
  66. void UnLinkScreen(theScreen)
  67. WSCREEN *theScreen;
  68. {
  69.    Forbid();
  70.    if (theScreen->Flags & WI_REFRESH) UnLinkRefresh(theScreen);
  71.    if (theScreen->Next) theScreen->Next->Prev = theScreen->Prev;
  72.    if (theScreen->Prev) theScreen->Prev->Next = theScreen->Next;
  73.       else FirstScreen = theScreen->Next;
  74.    Permit();
  75. }
  76.  
  77.  
  78. /*
  79.  *  NewWBScreen()
  80.  *
  81.  *  Make the specified screen the new WB screen
  82.  */
  83.  
  84. void NewWBScreen(theScreen)
  85. WSCREEN *theScreen;
  86. {
  87.    Forbid();
  88.    if (theScreen == RealWB) WBScreen = NULL; else WBScreen = theScreen;
  89.    Permit();
  90. }
  91.  
  92.  
  93. /*
  94.  *  WaitForWindows()
  95.  *
  96.  *  If the screen has foreign windows or icons on it
  97.  *    Get a signal for this screen and clear it
  98.  *    Set the Close signal and task for this screen
  99.  *    While there are still icons or windows, wait for them to be closed
  100.  *      (we will get a signal when they do)
  101.  *    Free the signal
  102.  */
  103.  
  104. void WaitForWindows(theScreen)
  105. WSCREEN *theScreen;
  106. {
  107.    ULONG mySignal;
  108.    UBYTE mySigBit;
  109.  
  110.    if (theScreen && (theScreen->Window || theScreen->IconRef))
  111.    {
  112.       mySigBit = AllocSignal(-ONE);
  113.       mySignal = (mySigBit == -ONE)? DEFAULTCLOSESIGNAL: (ONE<<mySigBit);
  114.       SetSignal(mySignal,0L);
  115.  
  116.       Forbid();
  117.       theScreen->CloseSignal = mySignal;
  118.       theScreen->CloseTask   = FindTask(NULL);
  119.       Permit();
  120.  
  121.       while (theScreen->Window || theScreen->IconRef) Wait(mySignal);
  122.  
  123.       if (mySigBit != -ONE) FreeSignal(mySigBit);
  124.    }
  125. }
  126.  
  127.  
  128. /*
  129.  *  StripMessages()
  130.  *
  131.  *  Start with the first message in the message port
  132.  *  While we are not at the tail of the list
  133.  *    If the message belongs to the window we are closing
  134.  *      remove it from the port and reply to it
  135.  *    Go on to the next message
  136.  */
  137.  
  138. static void StripMessages(thePort,theWindow)
  139. struct MsgPort *thePort;
  140. struct Window *theWindow;
  141. {
  142.    struct Node *theMessage,*nextMessage;
  143.    
  144.    theMessage = thePort->mp_MsgList.lh_Head;
  145.    while (theMessage->ln_Succ)
  146.    {
  147.       nextMessage = theMessage->ln_Succ;
  148.       if (INTUIMESSAGE->IDCMPWindow == theWindow)
  149.       {
  150.          Remove(theMessage);
  151.          ReplyMsg(theMessage);
  152.       }
  153.       theMessage = nextMessage;
  154.    }
  155. }
  156.  
  157.  
  158. /*
  159.  *  CloseIconWindow()
  160.  *
  161.  *  If we have a screen to work with
  162.  *    And it has a backdrop window
  163.  *      If the window is active, deactivate it
  164.  *      If the window's UserPort is the common one
  165.  *        Strip out any messages belonging to this window
  166.  *        Clear the UserPort
  167.  *        Clear the IDCMP flags so no messages appear while we close it
  168.  *      Close the window and clear the screen's backdrop pointer
  169.  */
  170.  
  171. void CloseIconWindow(theScreen)
  172. WSCREEN *theScreen;
  173. {
  174.    if (theScreen)
  175.    {
  176.       Forbid();
  177.       if (theScreen->BackDrop)
  178.       {
  179.          if (theScreen->BackDrop == ActiveWindow) SetActiveWindow(NULL);
  180.          if (theScreen->BackDrop->UserPort == wUserPort)
  181.          {
  182.             StripMessages(theScreen->BackDrop->UserPort,theScreen->BackDrop);
  183.             theScreen->BackDrop->UserPort = NULL;
  184.             ModifyIDCMP(theScreen->BackDrop,0L);
  185.          }
  186.          CloseWindow(theScreen->BackDrop);
  187.          theScreen->BackDrop = NULL;
  188.       }
  189.       Permit();
  190.    }
  191. }
  192.  
  193.  
  194. /*
  195.  *  FindWindow()
  196.  *
  197.  *  If we have a window to look for
  198.  *    Find the screen the window is on
  199.  *    If the screen was found
  200.  *      Look through the window list of the screen for the given window
  201.  *  Return the window or NULL
  202.  */
  203.  
  204. WBWINDOW *FindWindow(theWindow)
  205. struct Window *theWindow;
  206. {
  207.    WSCREEN *theScreen;
  208.    WBWINDOW *ChkWindow = NULL;
  209.    
  210.    if (theWindow)
  211.    {
  212.       Forbid();
  213.       theScreen = FindScreen(theWindow->WScreen);
  214.       if (theScreen)
  215.       {
  216.          ChkWindow = theScreen->Window;
  217.          while (ChkWindow && ChkWindow->Window != theWindow)
  218.             ChkWindow = ChkWindow->Next;
  219.       }
  220.       Permit();
  221.    }
  222.    return(ChkWindow);
  223. }
  224.  
  225.  
  226. /*
  227.  *  LinkWindow()
  228.  *
  229.  *  Add the window to the screen's window list
  230.  */
  231.  
  232. void LinkWindow(theWindow,theScreen)
  233. WBWINDOW *theWindow;
  234. WSCREEN *theScreen;
  235. {
  236.    Forbid();
  237.    theWindow->Screen = theScreen;
  238.    theWindow->Next = theScreen->Window; theWindow->Prev = NULL;
  239.    if (theScreen->Window) theScreen->Window->Prev = theWindow;
  240.    theScreen->Window = theWindow;
  241.    Permit();
  242. }
  243.  
  244.  
  245. /*
  246.  *  UnLinkWindow()
  247.  *
  248.  *  Remove the window from the screen's window list
  249.  */
  250.  
  251. void UnLinkWindow(theWindow)
  252. WBWINDOW *theWindow;
  253. {
  254.    Forbid();
  255.    if (theWindow->Next) theWindow->Next->Prev = theWindow->Prev;
  256.    if (theWindow->Prev) theWindow->Prev->Next = theWindow->Next;
  257.       else theWindow->Screen->Window = theWindow->Next;
  258.    Permit();
  259. }
  260.  
  261.  
  262. /*
  263.  *  NewIconWindow()
  264.  *
  265.  *  If the screen is screen WBENCHSCREEN, then this is the real WB screen
  266.  *  Set the backdrop window UserData to point to the screen structure
  267.  *  Send the backdro pto the back (in case there are other backdrop windows)
  268.  *  If the screen is only one plane deep
  269.  *    Get an IntuiText from the menu list
  270.  *    If the text pen is the same as the screen's block pen (ie, the text
  271.  *        would be the same color as the menu background)
  272.  *      Change the backdrop window's detail and block pens so that the menus
  273.  *        will sho up OK
  274.  *  Add the wIconify title to the backdrop window
  275.  *  Show the screen title for this screen
  276.  *  Give the backdrop window the common UserPort
  277.  *  Set the IDCMP classes for the messages we want to receive
  278.  *  Report that a new screen has openned
  279.  */
  280.  
  281. void NewIconWindow(theScreen)
  282. WSCREEN *theScreen;
  283. {
  284.    struct IntuiText *theText;
  285.    extern struct MenuItem IconMenu[];
  286.  
  287.    Forbid();
  288.    if ((theScreen->Screen->Flags & SCREENTYPE) == WBENCHSCREEN)
  289.       RealWB = theScreen;
  290.    Permit();
  291.    theScreen->BackDrop->UserData = (BYTE *)theScreen;
  292.    WindowToBack(theScreen->BackDrop);
  293.    if (theScreen->Screen->BitMap.Depth == 1)
  294.    {
  295.       theText = (struct IntuiText *)IconMenu[0].ItemFill;
  296.       if ((theText->FrontPen & 0x01) == theScreen->BackDrop->BlockPen)
  297.       {
  298.          theScreen->BackDrop->DetailPen = theText->FrontPen & 0x01;
  299.          theScreen->BackDrop->BlockPen = 1 - theScreen->BackDrop->DetailPen;
  300.       }
  301.    }
  302.    SetWindowTitles(theScreen->BackDrop,-1L,wIconifyTitle);
  303.    ShowTitle(theScreen->Screen,TRUE);
  304.    theScreen->BackDrop->UserPort = wUserPort;
  305.    ModifyIDCMP(theScreen->BackDrop,IDCMPFLAGS);
  306.    ReportMulti(WI_REPORTNEWSCREEN,theScreen->Screen,NULL);
  307. }
  308.  
  309.  
  310. /*
  311.  *  FindIcon()
  312.  *
  313.  *  If we have a window to look for
  314.  *    Find the window's screen
  315.  *    If it was found
  316.  *      If the window is not a wIconify backdrop window
  317.  *        Search through the icon list for the given icon
  318.  *      Otherwise (the window is the backdrop window)
  319.  *        Use the screen's icon
  320.  *  Return the icon found or NULL
  321.  */
  322.  
  323. WICONREF *FindIcon(theWindow,theScreen)
  324. struct Window *theWindow;
  325. WSCREEN **theScreen;
  326. {
  327.    WICONREF *theIcon = NULL;
  328.    
  329.    if (theWindow)
  330.    {
  331.       Forbid();
  332.       *theScreen = FindScreen(theWindow->WScreen);
  333.       if (*theScreen)
  334.       {
  335.          if (theWindow != (*theScreen)->BackDrop)
  336.          {
  337.             theIcon = (*theScreen)->IconRef;
  338.             while (theIcon && theIcon->Window != theWindow)
  339.                theIcon = theIcon->Next;
  340.          } else {
  341.             theIcon = &((*theScreen)->Icon);
  342.          }
  343.       }
  344.       Permit();
  345.    } else *theScreen = NULL;
  346.    return(theIcon);
  347. }
  348.  
  349.  
  350. /*
  351.  *  LinkIcon()
  352.  *
  353.  *  Link the Icon into the give screen's icon list
  354.  */
  355.  
  356. void LinkIcon(theIcon,theScreen)
  357. WICONREF *theIcon;
  358. WSCREEN *theScreen;
  359. {
  360.    Forbid();
  361.    theIcon->Screen = theScreen;
  362.    theIcon->Next = theScreen->IconRef; theIcon->Prev = NULL;
  363.    if (theScreen->IconRef) theScreen->IconRef->Prev = theIcon;
  364.    theScreen->IconRef = theIcon;
  365.    Permit();
  366. }
  367.  
  368.  
  369. /*
  370.  *  UnLinkIcon()
  371.  *
  372.  *  Remove the icon from the screen's icon list
  373.  */
  374.  
  375. void UnLinkIcon(theIcon)
  376. WICONREF *theIcon;
  377. {
  378.    Forbid();
  379.    if (theIcon->Next) theIcon->Next->Prev = theIcon->Prev;
  380.    if (theIcon->Prev) theIcon->Prev->Next = theIcon->Next;
  381.       else theIcon->Screen->IconRef = theIcon->Next;
  382.    Permit();
  383. }
  384.  
  385.  
  386. /*
  387.  *  RemoveAutoIcons()
  388.  *
  389.  *  If a screen was specified
  390.  *    Start with the first icon on the screen
  391.  *    While there are more icons
  392.  *      If the icon is so be removed automatically when the screen closes
  393.  *        If the remove event is to be reported, do so
  394.  *        If the icon has a window, restore the it
  395.  *        Delete the icon from memory
  396.  *      Go on to the next icon
  397.  */
  398.  
  399. void RemoveAutoIcons(theScreen)
  400. WSCREEN *theScreen;
  401. {
  402.    WICONREF *theIcon,*nextIcon;
  403.  
  404.    if (theScreen)
  405.    {
  406.       theIcon = theScreen->IconRef;
  407.       while (theIcon)
  408.       {
  409.          nextIcon = theIcon->Next;
  410.          if (theIcon->Icon.Flags & WI_AUTOREMOVE)
  411.          {
  412.             if (theIcon->Icon.Report & WI_REPORTAUTOREMOVE)
  413.                ReportEvent(WI_REPORTAUTOREMOVE,theIcon);
  414.             if (theIcon->Window) Restore(theIcon,TRUE);
  415.             DeleteIcon(theIcon);
  416.          }
  417.          theIcon = nextIcon;
  418.       }
  419.    }
  420. }
  421.  
  422.  
  423. /*
  424.  *  ClearAllIcons()
  425.  *
  426.  *  Remove the icons that can be removed automatically
  427.  *  Open all icons that have windows
  428.  *  While there are still icons on the screen, delete them
  429.  *    (probably not a good idea, but the wIconify window is going
  430.  *    to be closed, so the user won't be able to get to them anyway)
  431.  */
  432.  
  433. static void ClearAllIcons(theScreen)
  434. WSCREEN *theScreen;
  435. {
  436.    RemoveAutoIcons(theScreen);
  437.    OpenAllIcons(theScreen);
  438.    while (theScreen->IconRef) DeleteIcon(theScreen->IconRef);
  439. }
  440.  
  441.  
  442. /*
  443.  *  AttemptQuit()
  444.  *
  445.  *  If we have not got an end singal yet
  446.  *    Allocate one and clear it
  447.  *  Set the current WB screen to NULL so new windows will open on the WB
  448.  *  Start with the first screen
  449.  *  While there are more screens
  450.  *    If the screen has icons, try to clear them
  451.  *    Close the wIconify backdrop window
  452.  *    If the screen has no more foreign windows or icons
  453.  *      Remove the screen from the list
  454.  *      If the screen is one that wIconify created, close it
  455.  *      Free the screen structure
  456.  *    Otherwise (it has windows or icons on it, so can't be closed)
  457.  *      Count the number of screens that can't be closed yet
  458.  *    Go on to the next screen
  459.  *  Return TRUE if all screen's are clear, otherwise return FALSE
  460.  */
  461.  
  462. int AttemptQuit()
  463. {
  464.    WSCREEN *theScreen,*nextScreen;
  465.    int ScreenCount = 0;
  466.  
  467.    if (EndSignal == 0)
  468.    {
  469.       EndSigBit = AllocSignal(-ONE);
  470.       EndSignal = (EndSigBit == -ONE)? DEFAULTENDSIGNAL: (ONE<<EndSigBit);
  471.       SetSignal(EndSignal,0L);
  472.    }
  473.    WBScreen = NULL;
  474.  
  475.    Forbid();
  476.    theScreen = FirstScreen;
  477.    while (theScreen)
  478.    {
  479.       nextScreen = theScreen->Next;
  480.       if (theScreen->IconRef) ClearAllIcons(theScreen);
  481.       CloseIconWindow(theScreen);
  482.       if (theScreen->Window == NULL && theScreen->IconRef == NULL)
  483.       {
  484.          UnLinkScreen(theScreen);
  485.          if (theScreen->Flags & WI_WSCREEN) CloseScreen(theScreen->Screen);
  486.          FREESTRUCT(wScreen,theScreen);
  487.       } else ScreenCount++;
  488.       theScreen = nextScreen;
  489.    }
  490.    Permit();
  491.    return(ScreenCount == 0);
  492. }
  493.  
  494.  
  495. /*
  496.  *  FreeAllLists()
  497.  *
  498.  *  While there are more screens to look at
  499.  *    While there are more windows on the screen
  500.  *      Free the window structure and go on to the next one
  501.  *    While there are icons on the screen
  502.  *      If the icon was created by wIconify
  503.  *        Unlink the icon and cree it
  504.  *    Free the screen structure and go on to the next one
  505.  */
  506.  
  507. void FreeAllLists()
  508. {
  509.    WSCREEN *theScreen,*tmpScreen;
  510.    WBWINDOW *theWindow,*tmpWindow;
  511.    WICONREF *theIcon,*tmpIcon;
  512.  
  513.    theScreen = FirstScreen;
  514.    while (theScreen)
  515.    {
  516.       theWindow = theScreen->Window;
  517.       while (theWindow)
  518.       {
  519.          tmpWindow = theWindow;
  520.          theWindow = theWindow->Next;
  521.          FREESTRUCT(wbWindow,tmpWindow);
  522.       }
  523.       theIcon = theScreen->IconRef;
  524.       while (theIcon)
  525.       {
  526.          tmpIcon = theIcon;
  527.          theIcon = theIcon->Next;
  528.          if (tmpIcon->Icon.Flags & WI_SYSICON)
  529.          {
  530.             UnLinkIcon(tmpIcon);
  531.             FREESTRUCT(wIconRef,tmpIcon);
  532.          }
  533.       }
  534.       tmpScreen = theScreen;
  535.       theScreen = theScreen->Next;
  536.       FREESTRUCT(wScreen,tmpScreen);
  537.    }
  538. }
  539.